#pragma once

#include <thrust/extrema.h>

template <typename Container>
struct MinElement
{
  Container A;

  template <typename Range>
  MinElement(const Range& X)
    : A(X.begin(), X.end())
  {}

  void operator()(void)
  {
    thrust::min_element(A.begin(), A.end());
  }
  
  void reset(void)
  {
    // nothing to do
  }
};

template <typename Container,
          typename Compare>
struct MinElementComp
{
  Container A;
  Compare comp;

  template <typename Range>
  MinElementComp(const Range& X, Compare comp)
    : A(X.begin(), X.end()),
      comp(comp)
  {}

  void operator()(void)
  {
    thrust::min_element(A.begin(), A.end(), comp);
  }
  
  void reset(void)
  {
    // nothing to do
  }
};


template <typename Container>
struct MaxElement
{
  Container A;

  template <typename Range>
  MaxElement(const Range& X)
    : A(X.begin(), X.end())
  {}

  void operator()(void)
  {
    thrust::max_element(A.begin(), A.end());
  }
  
  void reset(void)
  {
    // nothing to do
  }
};

template <typename Container,
          typename Compare>
struct MaxElementComp
{
  Container A;
  Compare comp;

  template <typename Range>
  MaxElementComp(const Range& X, Compare comp)
    : A(X.begin(), X.end()),
      comp(comp)
  {}

  void operator()(void)
  {
    thrust::max_element(A.begin(), A.end(), comp);
  }
  
  void reset(void)
  {
    // nothing to do
  }
};

template <typename Container>
struct MinMaxElement
{
  Container A;

  template <typename Range>
  MinMaxElement(const Range& X)
    : A(X.begin(), X.end())
  {}

  void operator()(void)
  {
    thrust::minmax_element(A.begin(), A.end());
  }
  
  void reset(void)
  {
    // nothing to do
  }
};

template <typename Container,
          typename Compare>
struct MinMaxElementComp
{
  Container A;
  Compare comp;

  template <typename Range>
  MinMaxElementComp(const Range& X, Compare comp)
    : A(X.begin(), X.end()),
      comp(comp)
  {}

  void operator()(void)
  {
    thrust::minmax_element(A.begin(), A.end(), comp);
  }
  
  void reset(void)
  {
    // nothing to do
  }
};

